#include "process_pool.h"

int main(int argc,char** argv)
{
    ARGS_CHECK(argc, 3);

    // 1. 生成套接字描述符
    int sfd = socket(AF_INET, SOCK_STREAM, 0);

    
    struct sockaddr_in ser_addr; // 服务器信息结构体
    bzero(&ser_addr, sizeof(ser_addr));
    ser_addr.sin_family = AF_INET; // 使用IPv4
    ser_addr.sin_port = htons(atoi(argv[2])); // 端口号
    ser_addr.sin_addr.s_addr = inet_addr(argv[1]); // IP地址

    // 2. connect
    int ret = connect(sfd, (struct sockaddr *)&ser_addr, sizeof(ser_addr));
    ERROR_CHECK(ret, -1, "connect");

    // 记录下载时间
    struct timeval start, end;
    gettimeofday(&start, NULL);
    
    // 下载文件
    // 1. 接收文件名
    int data_len;
    char buf[1000]={0};
    ret = recv_n(sfd,&data_len,4); // 接收文件名长度
    SELFFUNC_ERR_CHECK(ret, "recv_n");
    ret = recv_n(sfd,buf,data_len); // 接收文件名
    SELFFUNC_ERR_CHECK(ret, "recv_n");
    int fd = open(buf,O_RDWR|O_CREAT,0666); // 创建新文件

    // 2. 接收文件大小
    off_t file_size;
    ret = recv_n(sfd, &data_len, 4);
    SELFFUNC_ERR_CHECK(ret, "recv_n");
    ret = recv_n(sfd, &file_size, sizeof(file_size));
    SELFFUNC_ERR_CHECK(ret, "recv_n");

    // 3. 接收文件内容，使用splice
    int pipefd[2] = {0};
    pipe(pipefd);
    off_t download_size = 0, last_size = 0, slipce_size;
    slipce_size = data_len / 10000; // 文件0.01%大小
    off_t splice_byte;

    while(download_size < file_size)
    {
        // 接收文件数据到管道
        splice_byte = splice(sfd, NULL, pipefd[1], NULL, 32768, SPLICE_F_MOVE | SPLICE_F_MORE);
        ERROR_CHECK(splice_byte, -1, "splice");
        // 将接收到的数据从管道写到文件里
        ret = splice(pipefd[0], NULL, fd, NULL, splice_byte, SPLICE_F_MOVE | SPLICE_F_MORE);
        ERROR_CHECK(ret, -1, "splice");

        download_size += ret;
        if (download_size - last_size > slipce_size)
        {
            printf("%6.2lf%%\r", (double)download_size / file_size * 100);
            fflush(stdout);
            last_size = download_size;
        }
    }
    
    gettimeofday(&end, NULL);
    printf("use time = %ld\n", (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec);
    
    close(fd);
    close(sfd);
}